package org.springblade.modules.digitalization.service.impl;

import com.sun.org.apache.xerces.internal.dom.DeferredTextImpl;
import jdk.internal.org.xml.sax.InputSource;
import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class XmlNoteTool {

	private static Element sortElement(Element element) {
		// Get and sort children by tag name
		NodeList children = element.getChildNodes();
		if (children.getLength() == 0) {
			return element;
		}

		Text text = null;
		// Create a list of child elements
		List<Element> childList = new ArrayList<>();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				childList.add((Element) child);
			} else if (child.getNodeType() == Node.TEXT_NODE) {
				text = (Text) child;
			}
		}
		childList.sort(Comparator.comparing(Element::getTagName));

		// Create a new element with sorted children
		Element sortedElement = element.getOwnerDocument().createElement(element.getTagName());
		for (Element child : childList) {
			Element sortChildElement = sortElement(child);
			sortedElement.appendChild(sortChildElement); // Recursively sort children
		}

		if (text != null) {
			sortedElement.appendChild(text);
		}

		// Copy attributes from the original element
		NamedNodeMap attributes = element.getAttributes();
		for (int i = 0; i < attributes.getLength(); i++) {
			Node attr = attributes.item(i);
			sortedElement.setAttribute(attr.getNodeName(), attr.getNodeValue());
		}
		return sortedElement;
	}

	public static String documentToString(Document doc) throws Exception {
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		Transformer transformer = transformerFactory.newTransformer();
		transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes");
		transformer.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, "xml");
		transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "UTF-8");

		DOMSource source = new DOMSource(doc);
		StringWriter writer = new StringWriter();
		StreamResult result = new StreamResult(writer);
		transformer.transform(source, result);
		return writer.toString();
	}

	public static String getSortedXmlContent(File inputFile) {
		try {
			// Parse the HTML document
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setIgnoringElementContentWhitespace(true);
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(inputFile);
			// Sort elements recursively
			Element sortedDocBody = sortElement(doc.getDocumentElement());
			// Create a new document and append sorted body
			Document sortedDoc = builder.newDocument();
			sortedDoc.appendChild(sortedDoc.importNode(sortedDocBody, true));
			String document = documentToString(sortedDoc);
			return document;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	public static void main(String... args) {

		String sortedXmlContent = getSortedXmlContent(new File("D:/data/test.xml"));
		System.out.println(sortedXmlContent);
	}

}
